package com.devenv.controller;

import com.devenv.common.PageRequest;
import com.devenv.common.PageResult;
import com.devenv.common.Result;
import com.devenv.dto.SoftwareDTO;
import com.devenv.dto.SoftwareVersionDTO;
import com.devenv.service.SoftwareService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.List;

/**
 * 软件管理控制器
 * 提供核心的软件管理功能，包含分页、搜索等
 */
@Slf4j
@RestController
@RequestMapping("/software")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
@Validated
@Tag(name = "软件管理", description = "软件信息的增删改查、搜索功能")
public class SoftwareController {

    private final SoftwareService softwareService;

    /**
     * 分页获取软件列表
     */
    @GetMapping("/page")
    @Operation(summary = "分页获取软件列表", description = "支持按分类、操作系统、关键词筛选的分页查询")
    public Result<PageResult<SoftwareDTO>> getSoftwarePage(
            @Valid PageRequest pageRequest,
            @Parameter(description = "软件分类") @RequestParam(required = false) String category,
            @Parameter(description = "操作系统") @RequestParam(required = false) String os,
            @Parameter(description = "搜索关键词") @RequestParam(required = false) String keyword) {
        
        log.info("分页查询软件列表: page={}, size={}, category={}, os={}, keyword={}", 
                pageRequest.getCurrent(), pageRequest.getSize(), category, os, keyword);
        
        PageResult<SoftwareDTO> pageResult = softwareService.findByPage(pageRequest, category, os, keyword);
        return Result.success(pageResult);
    }

    /**
     * 获取所有软件列表
     */
    @GetMapping
    @Operation(summary = "获取所有软件列表", description = "获取所有启用状态的软件，按优先级排序")
    public Result<List<SoftwareDTO>> getAllSoftware() {
        log.info("获取所有软件列表");
        List<SoftwareDTO> softwareList = softwareService.findAll();
        return Result.success(softwareList);
    }

    /**
     * 根据ID获取软件详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取软件详情", description = "根据软件ID获取详细信息，包含版本列表")
    public Result<SoftwareDTO> getSoftwareById(
            @Parameter(description = "软件ID") @PathVariable @NotNull Long id) {
        
        log.info("获取软件详情: id={}", id);
        SoftwareDTO software = softwareService.findById(id);
        return Result.success(software);
    }

    /**
     * 根据分类获取软件列表
     */
    @GetMapping("/category/{category}")
    @Operation(summary = "按分类获取软件", description = "获取指定分类下的所有软件")
    public Result<List<SoftwareDTO>> getSoftwareByCategory(
            @Parameter(description = "软件分类") @PathVariable @NotBlank String category) {
        
        log.info("按分类获取软件列表: category={}", category);
        List<SoftwareDTO> softwareList = softwareService.findByCategory(category);
        return Result.success(softwareList);
    }

    /**
     * 根据操作系统获取支持的软件
     */
    @GetMapping("/os/{os}")
    @Operation(summary = "按操作系统获取软件", description = "获取支持指定操作系统的软件")
    public Result<List<SoftwareDTO>> getSoftwareByOs(
            @Parameter(description = "操作系统") @PathVariable @NotBlank String os) {
        
        log.info("按操作系统获取软件列表: os={}", os);
        List<SoftwareDTO> softwareList = softwareService.findByOsSupport(os);
        return Result.success(softwareList);
    }

    /**
     * 搜索软件
     */
    @GetMapping("/search")
    @Operation(summary = "搜索软件", description = "根据关键词搜索软件名称、描述等")
    public Result<List<SoftwareDTO>> searchSoftware(
            @Parameter(description = "搜索关键词") @RequestParam @NotBlank String keyword) {
        
        log.info("搜索软件: keyword={}", keyword);
        List<SoftwareDTO> softwareList = softwareService.searchByKeyword(keyword);
        return Result.success(softwareList);
    }

    /**
     * 获取所有分类
     */
    @GetMapping("/categories")
    @Operation(summary = "获取所有分类", description = "获取系统中所有的软件分类")
    public Result<List<String>> getAllCategories() {
        log.info("获取所有软件分类");
        List<String> categories = softwareService.getAllCategories();
        return Result.success(categories);
    }

    /**
     * 获取软件版本列表
     */
    @GetMapping("/{id}/versions")
    @Operation(summary = "获取软件版本", description = "获取指定软件的所有版本信息")
    public Result<List<SoftwareVersionDTO>> getSoftwareVersions(
            @Parameter(description = "软件ID") @PathVariable @NotNull Long id) {
        
        log.info("获取软件版本列表: softwareId={}", id);
        List<SoftwareVersionDTO> versions = softwareService.getVersionsBySoftwareId(id);
        return Result.success(versions);
    }

    /**
     * 增加下载次数
     */
    @PostMapping("/{id}/download")
    @Operation(summary = "记录下载", description = "增加软件的下载计数")
    public Result<Void> incrementDownloadCount(
            @Parameter(description = "软件ID") @PathVariable @NotNull Long id) {
        
        log.info("记录软件下载: softwareId={}", id);
        softwareService.incrementDownloadCount(id);
        return Result.success();
    }

    // === 管理员功能 ===

    /**
     * 创建软件（需要管理员权限）
     */
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "创建软件", description = "创建新的软件信息（需要管理员权限）")
    public Result<SoftwareDTO> createSoftware(@Valid @RequestBody SoftwareDTO softwareDTO) {
        log.info("创建软件: name={}", softwareDTO.getName());
        SoftwareDTO createdSoftware = softwareService.createSoftware(softwareDTO);
        return Result.success(createdSoftware, "软件创建成功");
    }

    /**
     * 更新软件（需要管理员权限）
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "更新软件", description = "更新软件信息（需要管理员权限）")
    public Result<SoftwareDTO> updateSoftware(
            @Parameter(description = "软件ID") @PathVariable @NotNull Long id,
            @Valid @RequestBody SoftwareDTO softwareDTO) {
        
        log.info("更新软件: id={}, name={}", id, softwareDTO.getName());
        SoftwareDTO updatedSoftware = softwareService.updateSoftware(id, softwareDTO);
        return Result.success(updatedSoftware, "软件更新成功");
    }

    /**
     * 删除软件（需要管理员权限）
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "删除软件", description = "逻辑删除软件（需要管理员权限）")
    public Result<Void> deleteSoftware(
            @Parameter(description = "软件ID") @PathVariable @NotNull Long id) {
        
        log.info("删除软件: id={}", id);
        softwareService.deleteSoftware(id);
        return Result.success(null, "软件删除成功");
    }
}
